home *** CD-ROM | disk | FTP | other *** search
- /*
- * query.c : Programmatic Prospero interface to Archie
- *
- * Copyright (c) 1991 by the University of Washington
- *
- * For copying and distribution information, please see the file
- * <copyright.h>.
- *
- * Originally part of the Prospero Archie client by Clifford
- * Neuman (bcn@isi.edu). Modifications, addition of programmatic interface,
- * and new sorting code by George Ferguson (ferguson@cs.rochester.edu)
- * and Brendan Kehoe (brendan@cs.widener.edu).
- *
- * v2.0 - 04/23/93 (gf) - for xarchie 2.0 - and now we part company...
- * v1.3.2 - bpk - for Archie client 1.3.2
- * v1.2.0 - 09/17/91 (bpk) - added BULL & USG stuff, thanks to Jim Sillas
- * v1.1.3 - 08/30/91 (bpk) - cast index()
- * v1.1.2 - 08/20/91 (bcn) - make it do it properly (new invdatecmplink)
- * v1.1.1 - 08/20/91 (bpk) - made sorting go inverted as we purport it does
- */
- #include <copyright.h>
- #include <stdio.h>
- #include <pfs.h>
- #include <perrno.h>
- #include <archie.h>
-
- #include "config.h"
- #ifdef TM_IN_SYS_TIME
- # include <sys/time.h>
- #else
- # include <time.h>
- #endif
- #include "stringdefs.h"
- #include "xtypes.h"
- #include "db.h"
- #include "appres.h"
- #include "browser.h"
- #include "alert.h"
- #include "status.h"
- #include "debug.h"
- extern DbEntry *db;
-
- /* These are in dirsend.c */
- extern int client_dirsrv_timeout,client_dirsrv_retry,rdgram_priority;
-
- /* Functions defined here: */
- void queryItemAndParse(),queryHostAndParse(),queryLocationAndParse();
- VLINK stringQuery();
- int parseArchieQueryResults(), parseStringQueryResults();
- int handleProsperoErrors();
-
- static void doQueryAndParse();
- static void parseHostAndFilename(), parseAttributes();
-
- /* Data defined here */
- int pfs_debug;
-
- /* - - - - - - - - */
- /*
- * Main function to call to process a query from the user.
- */
- void
- queryItemAndParse(query)
- char *query;
- {
- char qstring[MAX_VPATH];
-
- DEBUG1("queryItemAndParse: \"%s\"\n",query);
- sprintf(qstring,"ARCHIE/MATCH(%d,%d,%c)/%s",
- appResources.maxHits,appResources.offset,appResources.searchType,
- query);
- doQueryAndParse(qstring);
- DEBUG0("queryItemAndParse: done\n");
- }
-
- /*
- * Main function to open a host specified by the user.
- */
- void
- queryHostAndParse(hostname)
- char *hostname;
- {
- char qstring[MAX_VPATH];
-
- DEBUG1("queryHostAndParse: \"%s\"\n",hostname);
- sprintf(qstring,"ARCHIE/HOST/%s",hostname);
- doQueryAndParse(qstring);
- DEBUG0("queryHostAndParse: done\n");
- }
-
- /*
- * Main function to open a host specified by the user.
- */
- void
- queryLocationAndParse(hostname,location)
- char *hostname,*location;
- {
- char qstring[MAX_VPATH];
-
- DEBUG2("queryLocationAndParse: \"%s:%s\"\n",hostname,location);
- sprintf(qstring,"ARCHIE/HOST/%s%s",hostname,location);
- doQueryAndParse(qstring);
- DEBUG0("queryLocationAndParse: done\n");
- }
-
- /*
- * Used by both query functions to send the string to Archie and interpret
- * the results into the browser.
- */
- static void
- doQueryAndParse(str)
- char *str;
- {
- VLINK links;
- int num;
-
- /* Send the query to Archie */
- DEBUG1("doQueryAndParse: \"%s\"\n",str);
- DEBUG0("calling stringQuery...\n");
- links = stringQuery(appResources.archieHost,str);
- DEBUG0("calling handleProsperoErrors...\n");
- (void)handleProsperoErrors();
- /* If we aborted or had an error, then don't clear the db */
- if (links == NULL ) {
- /* Wasn't an error... */
- if (perrno == PSUCCESS)
- status0("No matches -- Ready.");
- return;
- }
- /* Reset browser to leftmost position */
- resetBrowser();
- /* Empty (and free) previous contents of database */
- clearEntries(db);
- /* Process the results into the database */
- status0("Parsing...");
- DEBUG0("calling parseArchieQueryResults\n");
- switch(appResources.sortType) {
- case GfName:
- num = parseArchieQueryResults(db,links,cmpEntryNames);
- break;
- case GfDate:
- num = parseArchieQueryResults(db,links,cmpEntryDates);
- break;
- case GfWeight:
- num = parseArchieQueryResults(db,links,cmpEntryWeights);
- break;
- }
- /* Display results in browser */
- DEBUG0("calling displayEntries\n");
- displayEntries(db,0);
- status1("Found %d matches -- Ready",(char *)num);
- DEBUG0("doQueryAndParse: done\n");
- }
-
- /* - - - - - - - - */
- /*
- * Returns an unsorted, untranslated list of vlinks for string from host.
- */
- VLINK
- stringQuery(host,string)
- char *host,*string;
- {
- VLINK links; /* Matches returned by server */
- VDIR_ST dir_st; /* Filled in by get_vdir */
- PVDIR dir = &dir_st;
- VLINK p,nextp,r;
- int tmp;
-
- /* initialize Prospero globals from appResources */
- pfs_debug = appResources.debugLevel;
- rdgram_priority = appResources.niceLevel;
- client_dirsrv_timeout = appResources.timeout;
- client_dirsrv_retry = appResources.retries;
-
- /* Initialize Prospero structures */
- perrno = PSUCCESS; *p_err_string = '\0';
- pwarn = PNOWARN; *p_warn_string = '\0';
- vdir_init(dir);
-
- /* Retrieve the list of matches, return error if there was one */
- #if defined(MSDOS)
- if ((tmp=get_vdir(host,string,"",dir,
- (long)GVD_ATTRIB|GVD_NOSORT,NULL,NULL)) != 0) {
- #else
- if ((tmp=get_vdir(host,string,"",dir,
- GVD_ATTRIB|GVD_NOSORT,NULL,NULL)) != 0) {
- # endif
- perrno = tmp;
- return(NULL);
- }
-
- /* Save the links, and clear in dir in case it's used again */
- links = dir->links; dir->links = NULL;
-
- /* As returned, list is sorted by suffix, and conflicting */
- /* suffixes appear on a list of "replicas". We want to */
- /* create a one-dimensional list sorted by host then filename */
- /* and maybe by some other parameter */
-
- /* First flatten the doubly-linked list */
- for (p = links; p != NULL; p = nextp) {
- nextp = p->next;
- if (p->replicas != NULL) {
- p->next = p->replicas;
- p->next->previous = p;
- for (r = p->replicas; r->next != NULL; r = r->next)
- /*EMPTY*/ ;
- r->next = nextp;
- nextp->previous = r;
- p->replicas = NULL;
- }
- }
- perrno = PSUCCESS;
- return(links);
- }
-
- /* - - - - - - - - */
- /*
- * Here take the list of untranslated unsorted links and put them into the
- * database, translating and sorting as needed. The entries are added to
- * make a host-location-file hierarchy as appropriate for the top of the
- * database query for a query. Returns number of entries returned from query.
- * This routine is also used by the routine that reloads a database.
- */
- int
- parseArchieQueryResults(parent,links,cmp_proc)
- DbEntry *parent;
- VLINK links;
- int (*cmp_proc)();
- {
- VLINK vl;
- DbEntry *firstHost,*firstLoc;
- DbEntry *thisHost,*thisLoc,*thisFile;
- char hostname[MAX_VPATH],location[MAX_VPATH],filename[MAX_VPATH];
- int type;
- #ifdef MSDOS
- unsigned long size;
- #else
- int size;
- #endif
- char *modes,*gt_date,*archie_date;
- int num;
-
- DEBUG0("parseArchieQueryResults: parsing links...\n");
- num = 0;
- firstHost = firstLoc = NULL;
- for (vl=links; vl != NULL; vl = vl->next) {
- parseHostAndFilename(vl,hostname,location,filename);
- parseAttributes(vl,&type,&size,&modes,&archie_date,>_date);
- if (firstHost == NULL) {
- firstHost = thisHost = addEntry(parent,NULL);
- firstLoc = thisLoc = addEntry(firstHost,NULL);
- thisFile = addEntry(firstLoc,NULL);
- } else {
- if ((thisHost=findEntryFromString(parent,hostname)) == NULL)
- thisHost = addEntry(parent,NULL);
- if ((thisLoc=findEntryFromString(thisHost,location)) == NULL)
- thisLoc = addEntry(thisHost,NULL);
- thisFile = addEntry(thisLoc,NULL);
- }
- setEntryData(thisHost,hostname,DB_HOST,0,"","","",NULL);
- setEntryData(thisLoc,location,DB_LOCATION,0,"","","",NULL);
- setEntryData(thisFile,filename,type,size,modes,archie_date,gt_date,vl);
- num += 1;
- }
- DEBUG0("parseArchieQueryResults: sorting entries...\n");
- sortEntriesRecursively(parent,cmp_proc);
- DEBUG1("parseArchieQueryResults: returning %d matches\n",num);
- return(num);
- }
-
- /*
- * Like parseArchieQueryresults(), but all the entries for the links are
- * added as immediate children of parent, rather than a three-level tree.
- * This is used to expand the browser below some item.
- */
- int
- parseStringQueryResults(parent,links,cmp_proc)
- DbEntry *parent;
- VLINK links;
- int (*cmp_proc)();
- {
- VLINK vl;
- DbEntry *dbp;
- char hostname[MAX_VPATH],location[MAX_VPATH],filename[MAX_VPATH];
- int type,size;
- char *modes,*gt_date,*archie_date;
- int num;
-
- DEBUG0("parseStringQueryResults: parsing links...\n");
- num = 0;
- for (vl=links; vl != NULL; vl = vl->next) {
- parseHostAndFilename(vl,hostname,location,filename);
- parseAttributes(vl,&type,&size,&modes,&archie_date,>_date);
- dbp = addEntry(parent,NULL);
- setEntryData(dbp,filename,type,size,modes,archie_date,gt_date,vl);
- num += 1;
- }
- DEBUG0("parseStringQueryResults: sortign entries...\n");
- sortEntriesRecursively(parent,cmp_proc);
- DEBUG1("parseStringQueryResults: returning %d matches\n",num);
- return(num);
- }
-
- /*
- * Fills in hostname, location, and filename with the appropriately-translated
- * and adjusted information from the link vl.
- */
- static void
- parseHostAndFilename(vl,hostname,location,filename)
- VLINK vl;
- char *hostname,*location,*filename;
- {
- char *slash;
-
- DEBUG3(" input:host=\"%s\"\n filename=\"%s\"\n name=\"%s\"\n",
- vl->host,vl->filename,vl->name);
- /* If the link is for an Archie pseudo-directory, adjust names. */
- if (strcmp(vl->type,"DIRECTORY") == 0 &&
- strncmp(vl->filename,"ARCHIE/HOST",11) == 0) {
- strcpy(hostname,vl->filename+12);
- slash = index(hostname,'/');
- if (slash != NULL) {
- strcpy(filename,slash);
- *slash = '\0';
- } else
- strcpy(filename,"/");
- } else {
- /* else just use the names as is */
- strcpy(hostname,vl->host);
- strcpy(filename,vl->filename);
- }
- /* The "location" is the leading part of the pathname */
- strcpy(location,filename);
- slash = rindex(location,'/');
- /* If filename ends with slash, try going back one more slash */
- if (slash && *(slash+1) == '\0')
- slash = (char *)rindex(slash,'/');
- if (slash) {
- strcpy(filename,slash+1);
- *slash = '\0';
- } else
- strcpy(location,"/");
- /* If filename was /foo, then we need to leave the slash there */
- if (*location == '\0')
- strcpy(location,"/");
- DEBUG3(" output:host=\"%s\"\n location=\"%s\"\n filename=\"%s\"\n",
- hostname,location,filename);
- }
-
- /*
- * Fills in *sizep, *modesp, and archie_date with the information in the
- * attribute list of the link vl.
- */
- static void
- parseAttributes(vl,typep,sizep,modesp,archie_datep,gt_datep)
- VLINK vl;
- int *typep;
- #ifdef MSDOS
- unsigned long *sizep;
- #else
- int *sizep;
- #endif
- char **modesp,**archie_datep,**gt_datep;
- {
- static char date[64];
- PATTRIB ap;
- int gt_year,gt_mon,gt_day,gt_hour,gt_min;
- struct tm *presenttime;
- long now;
-
- (void)time(&now);
- presenttime = localtime(&now);
- if (strcmp(vl->type,"DIRECTORY") == 0) {
- *typep = DB_DIRECTORY;
- } else {
- *typep = DB_FILE;
- }
- *sizep = 0;
- *modesp = "";
- *archie_datep = "";
- *gt_datep = "";
- gt_year = gt_mon = gt_day = gt_hour = gt_min = 0;
- for (ap = vl->lattrib; ap; ap = ap->next) {
- if (strcmp(ap->aname,"SIZE") == 0) {
- #ifdef MSDOS
- sscanf(ap->value.ascii,"%lu",sizep);
- #else
- sscanf(ap->value.ascii,"%d",sizep);
- #endif
- } else if(strcmp(ap->aname,"UNIX-MODES") == 0) {
- *modesp = ap->value.ascii;
- } else if(strcmp(ap->aname,"LAST-MODIFIED") == 0) {
- *gt_datep = ap->value.ascii;
- sscanf(*gt_datep,"%4d%2d%2d%2d%2d",>_year,
- >_mon, >_day, >_hour, >_min);
- if ((12 * (presenttime->tm_year + 1900 - gt_year) +
- presenttime->tm_mon - gt_mon) > 6)
- sprintf(date,"%s %2d %4d",month_sname(gt_mon),
- gt_day, gt_year);
- else
- sprintf(date,"%s %2d %02d:%02d",month_sname(gt_mon),
- gt_day, gt_hour, gt_min);
- *archie_datep = date;
- }
- }
- }
-
- /*
- * Pops up alerts depending on perrno and pwarn.
- * Used in several places after calling Archie.
- */
- int
- handleProsperoErrors()
- {
- int err = 0;
-
- /* Error? */
- if (perrno != PSUCCESS) {
- if (p_err_text[perrno]) {
- if (*p_err_string)
- alert2("Prospero error: %.100s - %.100s",p_err_text[perrno],
- p_err_string);
- else
- alert1("Prospero error: %.200s",p_err_text[perrno]);
- } else
- alert1("Prospero error: Undefined error %d (prospero)",(char*)perrno);
- err = 1;
- }
- /* Warning? */
- if (pwarn != PNOWARN) {
- if (*p_warn_string)
- alert2("Prospero warning: %.100s - %.100s",
- p_warn_text[pwarn], p_warn_string);
- else
- alert1("Prospero warning: %.200s",p_warn_text[pwarn]);
- status0("Ready");
- }
- return(err);
- }
-